function memoize(func, resolver) {
      if (!isFunction(func)) {
        throw new TypeError;
      }
      var memoized = function() {
        var cache = memoized.cache,
            key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];

        return hasOwnProperty.call(cache, key)
          ? cache[key]
          : (cache[key] = func.apply(this, arguments));
      }
      memoized.cache = {};
      return memoized;
    }
Creates a function that memoizes the result of `func`. If `resolver` is
provided it will be used to determine the cache key for storing the result
based on the arguments provided to the memoized function. By default, the
first argument provided to the memoized function is used as the cache key.
The `func` is executed with the `this` binding of the memoized function.
The result cache is exposed as the `cache` property on the memoized function.

@static
@memberOf _
@category Functions
@param {Function} func The function to have its output memoized.
@param {Function} [resolver] A function used to resolve the cache key.
@returns {Function} Returns the new memoizing function.
@example

var fibonacci = _.memoize(function(n) {
  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
});

fibonacci(9)
// => 34

var data = {
  'fred': { 'name': 'fred', 'age': 40 },
  'pebbles': { 'name': 'pebbles', 'age': 1 }
};

// modifying the result cache
var get = _.memoize(function(name) { return data[name]; }, _.identity);
get('pebbles');
// => { 'name': 'pebbles', 'age': 1 }

get.cache.pebbles.name = 'penelope';
get('pebbles');
// => { 'name': 'penelope', 'age': 1 }