text:   // Swap out for Array.findIndex
    function arrayIndexOfComparer(array, item, comparer) {
      for (var i = 0, len = array.length; i < len; i++) {
        if (comparer(array[i], item)) { return i; }
      }
      return -1;
    }
  
    function HashSet(comparer) {
      this.comparer = comparer;
      this.set = [];
    }
    HashSet.prototype.push = function(value) {
      var retValue = arrayIndexOfComparer(this.set, value, this.comparer) === -1;
      retValue && this.set.push(value);
      return retValue;
    };
  
    /**
     *  Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.
     *  Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.
     *
     * @example
     *  var res = obs = xs.distinct();
     *  2 - obs = xs.distinct(function (x) { return x.id; });
     *  2 - obs = xs.distinct(function (x) { return x.id; }, function (a,b) { return a === b; });
     * @param {Function} [keySelector]  A function to compute the comparison key for each element.
     * @param {Function} [comparer]  Used to compare items in the collection.
     * @returns {Observable} An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.
     */
    observableProto.distinct = function (keySelector, comparer) {
      var source = this;
      comparer || (comparer = defaultComparer);
      return new AnonymousObservable(function (observer) {
        var hashSet = new HashSet(comparer);
        return source.subscribe(function (x) {
          var key = x;
  
          if (keySelector) {
            try {
              key = keySelector(x);
            } catch (e) {
              observer.onError(e);
              return;
            }
          }
          hashSet.push(key) && observer.onNext(x);
        },
        observer.onError.bind(observer),
        observer.onCompleted.bind(observer));
      });
    };
  