ENH: DataFrame isin
WIP for now.

See #4211 for more info.

A few things to check before this is ready to merge:

This is basically a convenience method.  I use the `Series` method for each column passed, and aggregate the methods sensibly.

A few questions before merge though:
- Do we have a preference for `any`/`all` vs. `and`/`or`?  Seems like `any/all` would be more consistent with other methods like `df.dropna(how='all')`
- I'm not thrilled about all the nested if statements.  The problem is accepting both dicts and just flat arrays as values.  The idea is to use dicts like `{colname: array_of_possible_values}` if the set of possible values to match against differs by columns (most likely case I think).  I need the extra nested if statement here:

``` python
        if how == 'and':
            if isinstance(values, dict):
                cond_n = len(values)
            else:
                cond_n = len(self.columns)  # Flat matching.
        elif how == 'or':
            cond_n = 1
```

since the two ways of calling will be a bit different.  If you're passing a dict it will probably just be df.isin(values=dict).  If you don't care which column matches what, the call will be df[subset_of_columns].isin(values).  It's messy, but it works.
- I check for empty values, and raise an error instead of just returning all `False`s.  Passing an empty list as values, it would actually would work.  `Series.isin([])` will return all Falses.  But it would fail on an empty dict, so I just check for it ahead of time and raise an error.
- Also, I may have messed up the history.  I thought I rebased and squashed everything into one commit, but apparently not.  I had some merge conflicts that I had to fix (just picking HEAD over the old stuff everywhere). I'll take a closer look at this.  Also I may have done `git pull` instead of `git pull --rebase` at some point.  Will that mess up the history?

Happy to move this to .13 also.
