Your problem is here:
has_many :attendees, :through => :checkins, :source => :user
has_many :cospeakers, :through => :checkins, :source => :user
The has_many through: is the same as has_and_belongs_to_may, it's just the linking table has a custom name. You're essentially saying "event attendees are any user that is in the checkins table" and "event cospeakers are any user that is in the checkins table". You can see why that will return the same result.
What you need to do is add a flag to the checkins table and then add a condition to the has_many through:. Assuming you add a "is_cospeaker" boolean to the checkins table, you can do this:
has_many :attendees, through: :checkins, source: :user, conditions: {is_cospeaker: false}
has_many :cospeakers, through: :checkins, source: :user, conditions: {is_cospeaker: true}
(Note, that's Ruby 1.9+ hash syntax. Hopefully, you are using Ruby 1.9 or 2.0)