code: public static <T> Collection<T> unique(Collection<T> self, boolean mutate, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure closure) {
          // use a comparator of one item or two
          int params = closure.getMaximumNumberOfParameters();
          if (params == 1) {
              self = unique(self, mutate, new OrderBy<T>(closure, true));
          } else {
              self = unique(self, mutate, new ClosureComparator<T>(closure));
          }
          return self;
      }
docs: A convenience method for making a collection unique using a Closure to determine duplicate (equal) items.
  If mutate is true, it works on the receiver object and returns it. If mutate is false, a new collection is returned.
  <p>
  If the closure takes a single parameter, each element from the Collection will be passed to the closure. The closure
  should return a value used for comparison (either using {@link java.lang.Comparable#compareTo(java.lang.Object)} or
  {@link java.lang.Object#equals(java.lang.Object)}). If the closure takes two parameters, two items from the collection
  will be passed as arguments, and the closure should return an int value (with 0 indicating the items are not unique).
  <pre class="groovyTestCase">
  def orig = [1, 3, 4, 5]
  def uniq = orig.unique(false) { it % 2 }
  assert orig == [1, 3, 4, 5]
  assert uniq == [1, 4]
  </pre>
  <pre class="groovyTestCase">
  def orig = [2, 3, 3, 4]
  def uniq = orig.unique(false) { a, b {@code ->} a {@code <=>} b }
  assert orig == [2, 3, 3, 4]
  assert uniq == [2, 3, 4]
  </pre>
  
  @param self    a Collection
  @param mutate  false will always cause a new list to be created, true will mutate lists in place
  @param closure a 1 or 2 arg Closure used to determine unique items
  @return self   without any duplicates
  @since 1.8.1