Here's what I ended up doing. I made a subclass of NSTextView and overrode mouseDown: as follows...
- (void)mouseDown:(NSEvent *)theEvent
{
    // Notify delegate that this text view was clicked and then
    // handled the click natively as well.
    [[self myTextViewDelegate] didClickMyTextView:self];
    [super mouseDown:theEvent];
}
I'm reusing NSTextView's standard delegate...
- (id<MyTextViewDelegate>)myTextViewDelegate
{
    // See the following for info on formal protocols:
    // stackoverflow.com/questions/4635845/how-to-add-a-method-to-an-existing-protocol-in-cocoa
    if ([self.delegate conformsToProtocol:@protocol(MyTextViewDelegate)]) {
        return (id<MyTextViewDelegate>)self.delegate;
    }
    return nil;
}
And in the header...
@protocol MyTextViewDelegate <NSTextViewDelegate>
- (void)didClickMyTextView:(id)sender;
@end
In the delegate, I implement didClickMyTextView: to select the row.
- (void)didClickMyTextView:(id)sender
{
    // User clicked a text view. Select its underlying row.
    [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:[self.tableView rowForView:sender]] byExtendingSelection:NO];
}