code: function(fn, arg1, arg2) {
      var hashFn, limit, prop;
      if (isNumber(arg1)) {
        limit = arg1;
      } else {
        hashFn = arg1;
        limit  = arg2;
      }
      if (isString(hashFn)) {
        prop = hashFn;
        hashFn = function(obj) {
          return deepGetProperty(obj, prop);
        };
      } else if (!hashFn) {
        hashFn = collectArguments;
      }
      return createHashedMemoizeFunction(fn, hashFn, limit);
    }
docs: *
  @method memoize([hashFn], [limit])
  @returns Function
  @short Creates a function that will memoize results for unique calls.
  @extra `memoize` can be thought of as a more powerful `once`. Where `once`
  will only call a function once ever, memoized functions will be
  called once per unique call. A "unique call" is determined by the
  return value of [hashFn], which is passed the arguments of each call.
  If [hashFn] is undefined, it will deeply serialize all arguments,
  such that any different argument signature will result in a unique
  call. [hashFn] may be a string (allows `deep properties`) that acts
  as a shortcut to return a property of the first argument passed.
  [limit] sets an upper limit on memoized results. The default is no
  limit, meaning that unique calls will continue to memoize results.
  For most use cases this is fine, however [limit] is useful for more
  persistent (often server-side) applications for whom memory leaks
  are a concern.
  
  @example
  
  var fn = logHello.memoize();
  fn(1); fn(1); fn(2); -> logs twice, memoizing once
  
  var fn = calculateUserBalance.memoize('id');
  fn(Harry); fn(Mark); fn(Mark); -> logs twice, memoizing once
  
  @param {string|Function} [hashFn]
  @param {number} [limit]
  
  *